package org.kanstantin.nwscan.crawler;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
import org.apache.lucene.store.NIOFSDirectory;
import org.apache.lucene.util.NumericUtils;
import org.apache.lucene.util.Version;


import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.logging.Logger;


/**
 * @author kanstantin
 *
 */
public class LuceneIndexWriter implements ResultsWritable {
	private File outputDir;
    private IndexWriter writer;
    private final static Logger LOG = Logger.getLogger(LuceneIndexWriter.class.getName());
    private DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
	public LuceneIndexWriter() {

    }
    
    public void setOutputDir(File outputDir) {
		this.outputDir = outputDir;
	}

	public Document createDocument(SearchResult r) {
        LOG.finest(String.format("%s|%s|%s|%s|%s|%s|%s\n", r.getHost(), r.getShare(), r.getPath(), r.getFilename(),
                r.getExtension(), r.getSize(), dateFormat.format(r.getCreated())));

        Document doc = new Document();
        doc.add(new Field("host", r.getHost(), Field.Store.YES, Field.Index.ANALYZED));
        doc.add(new Field("share", r.getShare(), Field.Store.YES, Field.Index.ANALYZED));
        doc.add(new Field("path", r.getPath(), Field.Store.YES, Field.Index.ANALYZED));
        doc.add(new Field("filename", r.getFilename(), Field.Store.YES, Field.Index.ANALYZED));
        doc.add(new Field("ext", (r.getExtension() == null) ? "" : r.getExtension(), Field.Store.YES, Field.Index.ANALYZED));

//        doc.add(new Field("size", NumericUtils.longToPrefixCoded(r.getSize()), Field.Store.YES, Field.Index.NOT_ANALYZED));
		NumericField numericField = new NumericField("size", Field.Store.YES, true);
		numericField.setLongValue(r.getSize());
		doc.add(numericField);

        doc.add(new Field("created", DateTools.dateToString(r.getCreated(), DateTools.Resolution.SECOND), Field.Store.YES, Field.Index.NOT_ANALYZED));
        return doc;
    }
    @Override
	public boolean save(SearchResult r) {
		if (writer == null) {
			openOutput();
		}

		Document doc = createDocument(r);
        try {
            writer.addDocument(doc);
        }
        catch (Exception ex) {
            throw new RuntimeException("Failed to index " + r.getPath(), ex);
        }
        return true;
             
	}

    public void close() {
        try {
            writer.close();
        }
        catch (Exception ex) {
            throw new RuntimeException("Failed to close write ", ex);
        }
            
            
    }
	@Override
	public boolean save(List<SearchResult> results) {
		for (SearchResult searchResult: results) {
			save(searchResult);
		}
		return true;
	}

	private void openOutput() {

        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
        IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_30, analyzer);
        
        Directory dir;
        try {
            dir = new NIOFSDirectory(outputDir);
            writer = new IndexWriter(dir, cfg);
        }
        catch (IOException ex) {
            throw new RuntimeException("Failed to open dir ", ex);
        }
        
                
	}

}
